﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Reflection;
using System.Collections.Generic;

using SBPweb.Forge.Contracts.Events;

using SBPweb.PROvibe.Business.Shared.Contracts.Content;

using SBPweb.PROvibe.Business.Client.Library.Content;
using SBPweb.PROvibe.Business.Client.Library.Modularity;
using SBPweb.PROvibe.Business.Client.Library.Services.LayoutConnector;

using SBPweb.PROvibe.Presentation.Client.Controls.Containers;

namespace SBPweb.PROvibe.Modules.Client.Navigator.Pages
{

    public partial class Main : ContainerUserControl
    {

        #region Private fields

        private ThemeManager themeManager;
        private List<Control> listControls;

        #endregion

        #region Constructor logic

        public Main()
        {
            listControls = new List<Control>();
            containers.Add(new ContainerDescriptor(ContainerIdConstants.MainMenu));
            containers.Add(new ContainerDescriptor(ContainerIdConstants.NavigationPanel));
            containers.Add(new ContainerDescriptor(ContainerIdConstants.OverlayPanel));
            LayoutProviderClient lpc = new LayoutProviderClient();
            lpc.GetLayoutThemeCompleted += new EventHandler<GetLayoutThemeCompletedEventArgs>(OnGetLayoutThemeCompleted);
#if CLIENTONLY
            lpc.GetLayoutThemeSync(Application.Current.Host.Source.ToString());
#else
            lpc.GetLayoutThemeAsync(Application.Current.Host.Source.ToString());
#endif
        }

        #endregion

        #region Methods

        private void ContentFrame_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            TypeDescriptor? td = TypeDescriptor.GetDescriptorByPath(e.Uri.OriginalString);
            if (td.HasValue)
            {
                ContentItemDescriptor cId = new ContentItemDescriptor(td.Value, new ContainerDescriptor(ContainerIdConstants.NavigationPanel));
                ModuleLoader.CreateInstance<Control>(td.Value, null, cId);
                e.Cancel = true;
            }
        }

        // After the Frame navigates, ensure the HyperlinkButton representing the current page is selected
        private void ContentFrame_Navigated(object sender, NavigationEventArgs e)
        {
            foreach (UIElement child in LinksStackPanel.Children)
            {
                HyperlinkButton hb = child as HyperlinkButton;
                if (hb != null && hb.NavigateUri != null)
                {
                    if (hb.NavigateUri.ToString().Equals(e.Uri.ToString()))
                    {
                        VisualStateManager.GoToState(hb, "ActiveLink", true);
                    }
                    else
                    {
                        VisualStateManager.GoToState(hb, "InactiveLink", true);
                    }
                }
            }
        }

        // If an error occurs during navigation, show an error window
        private void ContentFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            e.Handled = true;
            ChildWindow errorWin = new Views.Error(e.Uri);
            errorWin.Show();
        }

        private void ContainerUserControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            UpdateControlSizes();
        }

        private void OnGetLayoutThemeCompleted(object sender, GetLayoutThemeCompletedEventArgs e)
        {
            themeManager = new ThemeManager(Application.Current);
            themeManager.ThemeApplied += new EventHandler(OnThemeManagerThemeApplied);

            themeManager.ApplyTheme(this, e.Result);
        }

        private void OnThemeManagerThemeApplied(object sender, EventArgs e)
        {
            InitializeComponent();
            InitializeControls();
        }

        protected override void SetContent(ContainerDescriptor container, object content)
        {
            UIElement element = content as UIElement;
            switch (container.ContainerId)
            {
                default:
                case ContainerIdConstants.NavigationPanel:
                    if (content is ChildWindow)
                    {
                        (content as ChildWindow).Show();
                    }
                    else
                    {
                        ContentFrame.Content = element;
                    }
                    break;
                case ContainerIdConstants.MainMenu:
                    LinksStackPanel.Children.Add(element);
                    break;
                case ContainerIdConstants.OverlayPanel:
                    listControls.Add(content as Control);
                    OverlayCanvas.Children.Add(element);
                    UpdateControlSizes();
                    break;
                case ContainerIdConstants.WindowManager:
                    UserControlWindow ucw = new UserControlWindow();
                    ucw.Content = content as Control;
                    ucw.ParentLayoutRoot = LayoutRoot;
                    ucw.Show();
                    break;
            }
        }

        private void UpdateControlSizes()
        {
            foreach (Control c in listControls)
            {
                double? dT = null;
                double? dL = null;
                try { dT = (double)c.GetValue(Canvas.TopProperty); }
                catch { }
                try { dL = (double)c.GetValue(Canvas.LeftProperty); }
                catch { }

                switch (c.HorizontalAlignment)
                {
                    default:
                        break;
                    case HorizontalAlignment.Stretch:
                        if (dT.HasValue)
                        {
                            c.Width = ActualWidth - dL.Value;
                        }
                        break;
                    case HorizontalAlignment.Right:
                        c.SetValue(Canvas.LeftProperty, ActualWidth - c.Width);
                        break;
                }
                switch(c.VerticalAlignment)
                {
                    default:
                        break;
                    case VerticalAlignment.Stretch:
                        if (dT.HasValue)
                        {
                            c.Height = ActualHeight - dT.Value;
                        }
                        break;
                    case VerticalAlignment.Bottom:
                        c.SetValue(Canvas.TopProperty, ActualHeight - c.Height);
                        break;
                }
            }
        }

        private void InitializeControls()
        {
            ApplicationNameTextBlock.Text = Application.Current.Host.InitParams["ApplicationName"];
            InitializeContents();
            ExtendableApplication.Put<Panel>("RootPanel", LayoutRoot);
        }

        #endregion

    }

}